#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include "../common/error.h"
#include "../common/memory.h"
#include "../common/debug.h"
#include <pthread.h>
#include <fcntl.h>

#define MAX_CLIENTS		5
#define IP_MAX_LEN		INET_ADDRSTRLEN

#define	TRANSMIT_WRITE	'w'
#define	TRANSMIT_READ	'r'

//#define CONNECTION_DEAD_SOCKET	-1

#define nwrite(sock,data,len)	transmit(sock,data,len,TRANSMIT_WRITE)
#define nread(sock,data,len)	transmit(sock,data,len,TRANSMIT_READ)

//criteri di valutazione e settaggi dei socket relativi ad una connection
#define valid_connection(c)		(1)
#define valid_connection_client(c)	(c->status&CONNECTION_STATUS_CLIENT_CONNECTED)
#define valid_connection_server(c)	(c->sock_s>=0)
#define socket_invalidate(s)		s=-1
#define valid_socket(s)			(s>0)
#define connection_is_a_listener(c)	(c->type&CONNECTION_TYPE_LISTEN)

//lunghezza del mac address restituito da get_mac_address()
#define MAC_HWADDRESS_LEN 6
#define LOCAL_IF_NAME "eth0"

struct ifreq if_info;


#ifndef __CONNECT_H__
#define __CONNECT_H__

void* (*client_f)(void *);
void* client_p;

//tipi di connection
enum {
	CONNECTION_TYPE_CONNECT = 0x01,		//per una connection di scambio dati
	CONNECTION_TYPE_LISTEN = 0x02		//per una connection che accetti connection di scambio dati
};

//stati di connection
//utilizzati in OR con lo status per settare il bit corrispondente
enum {
	//indicano rispettivamente che client e server hanno stabilito con successo la connessione al socket remoto
	CONNECTION_STATUS_CLIENT_CONNECTED = 0x01,
 	CONNECTION_STATUS_SERVER_CONNECTED = 0x02
};

//mantiene informazioni su un endpoint della connection
typedef struct {
	//int port;
	struct sockaddr *saddr;
	size_t sa_len;
} endpoint;

//specifica i parametri della connessione
typedef struct {
	int domain;
	int type;
	int protocol;
	int backlog;
	int howShutdown;
} connection_params;

//identifica una connection composta da una coppia di connessioni, rispettivamente con funzioni server e client
typedef struct {
	int sock_s, sock_c;		//socket di connessione
	unsigned int status;		//maschera di bit che indica lo stato della connection
	pthread_mutex_t mtx_c;		//mutex per l'accesso alla connessione client
	char *address;			//indirizzo del socket remoto in ascolto
	int listening_port;		//porta del socket remoto in ascolto
	unsigned int type;		//tipo di connection
	endpoint *local, *remote;	//endpoint della connection
	connection_params *cp;		//parametri di connessione utilizzati
} connection;
#endif

//lock ed unlock del mutex relativo al client di una connection
#define lock_client(x)		pthread_mutex_lock(&x->mtx_c)
#define unlock_client(x)	pthread_mutex_unlock(&x->mtx_c)

void printf_connection(connection*);


int connect_TCP(connection*);
//void listen_TCP(connection*);
connection* do_accept(connection*);
//int do_close(connection*);

in_addr_t get_my_address(int);
int transmit(int, void*, size_t, char);

//connection* clientTCP(char*, int);
connection* serverTCP(int);

